Regulární výrazy

Top  Prev  Next

PSPad od verze 3.6.0 podporuje hledání pomocí regulárních výrazů

 

Co jsou to regulární výrazy ?

Regulární výrazy jsou mocný nástroj pro hledání textových řetězců pomocí vzorů. Speciální předdefinované metaznaky dovolují specifikovat, zda hledaný řetězec leží na začátku nebo na konci textu / řádku, umožňuje specifikovat znaky, který řetězec obsahuje apod.

Z počátku vám to určitě bude připadat složité, ale po seznámení zjistíte, že je to velmi užitečný nástroj.

 

Jednoduché znaky

Každý znak zastupuje sebe. Je to jako při normálním hledání. Pokud zadáte slovo jelen, bude se hledat "jelen". Escape sekvence začíná znakem \. Existují některé speciální znaky, např. ^, který znamená, že se bude hledat na začátku řádku. Pokud ale budete chtít přímo znak ^, musíte zadat \^. Podobně pro hledání samotného znaku \ je třeba zadat \\.

 

Escape sekvence

Znaky můžou být specifikovány pomocí escape sekvence. \n je nový řádek, \t tabulátor apod. Znaky je možné také zadat pomocí jejich ASCII hodnoty. \xnn je hledání znaku, kde nn je jeho ASCII hodnota vyjádřená v šestnáctkové soustavě.

 

\xnn znak s šestnáctkovou ASCII hodnotou nn

\t   tabulátor (stejné jako \x09

\n   nový řádek, stejné jako \x0a

\r   CR, stejné jako \x0d

\f   FF, stejné jako \x0c

\a   BEL, stejné jako \x07

\e   ESC, stejné jako \x1b

 

Příklady:

 

jel\x20en najde slovo "jel en" (s mezerou uprostřed)

\tjelen najde slovo "jelen", před kterým je tabulátor

 

Skupiny (třídy) znaků

Je možné specifikovat skupiny znaků. Tato skupina je uzavřena v []. Text bude nalezen, pokud vyhovuje jeden znak ze seznamu. Pokud první znak za závorkou je ^, znamená to, že v textu nesmí být obsažen žádný znak ze seznamu.

 

Příklady:

jel[aei]n najde slova "jelan", "jelen", "jelin"

jel[^ai]n najde slovo "jelen", ale nenajde "jelin", "jelan" atd.

 

Znak - znamená rozsah znaků. Potom a-z znamená jakýkoliv znak v rozsahu "a" až "z".

Pokud chcete hledat znak - samotný, je třeba jej uvést na začátku / konci seznamu, nebo jej uvést pomocí \.

 

Příklady:

[-az]     vyhovují znaky "a", "z" a "-"

[az-]     vyhovují znaky "a", "z" a "-"

[a\-z]   vyhovují znaky "a", "z" a "-"

[a-z]     vyhovují všechny znaky v rozsahu "a" až "z"

[\n-\x0D] vyhovují znaky s ASCII hodnotou #10,#11,#12,#13

[\d-t]   vyhovují čísla, "-" a "t"

[]-a]     vyhovuje znak v rozsahu "]" až "a"

 

Metaznaky - oddělovače řádků

^ začátek řádku

$ konec řádku

\A začátek textu

\Z konec textu

. jakýkoliv znak

 

Příklady:

^jelen   "jelen", ale pouze pokud je na začátku řádku

jelen$   "jelen", ale pouze pokud je na konci řádku

^jelen$ "jelen", ale pouze pokud na řádku není nic jiného

jele.n   "jel"jakýkoliv_znak"n"

 

Metaznaky - předdefinované skupiny

\w písmena včetně "_"

\W čísla a písmena

\d čísla

\D nečíselné znaky

\s jakákoliv mezera (stejné jako [ \t\n\r\f])

\S nemezerový znak

 

Příklady:

jel\dn     znamená "jel1n", "jel7n", ale ne "jelen"

jel[\w\s]n znamená "jelen", "jel n", ale ne "jel2n", "jel=n" apod.

 

Metaznaky - čítače

Jakýkoliv znak může být následován čítačem. Lze tak určit počet výskytů předchozího znaku, metaznaku nebo výrazu.

 

hladové

*     žádný nebo více výskytů znaku, podobně jako {0,}

+     jeden nebo více výskytů znaku, podobně jako {1,}

?     žádný nebo jeden výskyt znaku, podobně jako {0,1}

{n}   přesně n výskytů

{n,}   nejméně n výskytů

{n,m} nejméně n-krát, ale ne víc než m-krát

nehladové

*?     žádný nebo více výskytů, podobně jako {0,}?

+?     jeden nebo více výskytů, podobně jako {1,}?

??     žádný nebo jeden výskyt, podobně jako {0,1}?

{n}?   přesně n výskytů

{n,}? nejméně n výskytů

{n,m}? nejméně n-krát, ale ne víc než m-krát

 

Příklady:

jel.*n     najde "jelen", "jel87hsgdn", "jeln"...

jel.+n     najde "jelen", "jel87hsgdn", ale ne "jeln"

jel.?n     najde "jelen", "jeln", ale ne "jel87hsgdn"

jele{2}n   najde "jeleen"

jele{2,}n najde "jeleen", "jeleeen", "jeleeeen"...

jele{2,3}n najde "jeleen", "jeleeen", ale ne "jeleeeen"

 

Malé vysvětlení o "hladovosti". "Hladový" vrací tolik, kolik je možné. "Nehladový" vrací tak málo, jak je možné. Např. b+ a b* aplikované na řetězec 'abbbbc' vrací 'bbbb', b+? vrací 'b', b*? vrátí prázdný řetězec, b{2,3}? vrátí 'bb', b{2,3} vrátí 'bbb'.

 

Metaznaky - alternativy

Ve vzoru lze také specifikovat sérii alternativ, jako oddělovač slouží znak |.

Např. jelen|jelan|jelin najde "jelen", "jelan" nebo "jelin" (podobně jako jel(e|a|i)n)

Nezapomeňte ale na to, že znak | uvnitř [] je interpretován jako obyčejný znak !

Pokud tedy uvedete [jelen|jelan|jelin], ve skutečnosti jste zadali, že chcete hledat jeden ze znaků "jeln|ai"

 

Příklad:

jel(en|ínek) najde "jelen" nebo "jelínek"

 

Metaznaky - vnořené výrazy

Konstrukce (...) může být použita také pro definici vnořených výrazů.

 

Příklady:

(jelen){8,10} najde řetězec, který obsahuje 8, 9 nebo 10 výskytů "jelen"

jel([0-9]|e+)n najde "jel0n", "jel3n", "jelen", "jeleen", "jeleeen" ...

 

Metaznaky - zpětné reference

Metaznaky od \1 do \9 jsou interpretovány jako zpětná reference.

 

Příklady:

(.)\1+         najde "aaaa" a "cc" (2 a více stejných znaků)

(.+)\1+       najde "abab" a "123123" (opakující se posloupnosti znaků)

(['"]?)(\d+)\1 najde '"13" (v dvojitých uvozovkách) nebo '4' (v jednoduchých uvozovkách) nebo 77

 


Pár příkladů z praxe:

 

Hledání

 

Nahrazování

regulární výrazy umožňují použít v nahrazování i části hledaných řetězců. Shluky znaků, uzavřené v závorkách v části hledat jsou vráceny v proměnných $1..$n, takže je možné je použít v nahradit. Viz následující příklady:

 

hledat: ([0-9]{2}).([0-9]{2}).([0-9]{4})

nahradit: $3-$2-$1

hledat: ([0-9]{2}):([0-9]{2})

nahradit: $2-$1

hledat: ;

nahradit: \n

upozornění: kurzor na konec textu a hledat směrem "vzad"

hledat: \s+

nahradit: \n

upozornění: kurzor na konec textu a hledat směrem "vzad"

 

Komplexnější případ z praxe

Měl jsem seznam tagů ve tvaru tag - popis

Potřeboval jsem jej dostat do definice pole ve tvaru a[index] := 'tag';

  1. zbavíme se popisu, takže nahradíme -.* za "nic"
  2. pomocí vložení číslování do řádků jsem si nechal na začátek každého řádku vložit číslo s dvěmi číslicemi. Takže seznam vypadal nějak takto: nn. tag
  3. pomocí dalšího nahrazení ([0-9]{2})\..(.*) za a[$1] := '$2'; jsem dosáhl výsledného tvaru

 


Pro vysvětlení syntaxe byl použit (přeložen) text z nápovědy k implementaci regulárních výrazů od Andrey V. Sorokina (http://regexpstudio.com/)